home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_149 / less / src / main.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  550 lines

  1. /*
  2.  * Entry point, initialization, miscellaneous routines.
  3.  */
  4.  
  5. #include "less.h"
  6. #include "position.h"
  7. #include <setjmp.h>
  8.  
  9. public int    ispipe;
  10. public jmp_buf    main_loop;
  11. public char *    first_cmd;
  12. public char *    every_first_cmd;
  13. public int    new_file;
  14. public int    is_tty;
  15. public char     current_file[FILENAME];
  16. public char     previous_file[FILENAME];
  17. public POSITION    prev_pos;
  18. public int    any_display;
  19. public int    ac;
  20. public char **    av;
  21. public int     curr_ac;
  22. #if LOGFILE
  23. public int    logfile = -1;
  24. public int    force_logfile = 0;
  25. public char *    namelogfile = NULL;
  26. #endif
  27. #if EDITOR
  28. public char *    editor;
  29. #endif
  30.  
  31. extern int file;
  32. extern int nbufs;
  33. extern int sigs;
  34. extern int quit_at_eof;
  35. extern int p_nbufs, f_nbufs;
  36. extern int back_scroll;
  37. extern int top_scroll;
  38. extern int sc_height;
  39. extern int errmsgs;
  40.  
  41. #ifdef AMIGA
  42. /********** amiga **************/
  43. #include <ctype.h>
  44. long CurrentDir();
  45. int called_from_WB = 0;
  46.  
  47. char prog_name[32];
  48.  
  49. /* max items and chars that *.c can expand to */
  50. #define MAXTEMPLATES 100
  51. #define MAXARGVCHARS 1000
  52. public char    local_buffer[MAXARGVCHARS];
  53. public char    *local_av[MAXTEMPLATES];
  54. #endif
  55.  
  56. /*
  57.  * Edit a new file.
  58.  * Filename "-" means standard input.
  59.  * No filename means the "current" file, from the command line.
  60.  */
  61.     public void
  62. edit(filename)
  63.     register char *filename;
  64. {
  65.     register int f;
  66.     register char *m;
  67.     POSITION initial_pos;
  68.     char message[100];
  69.     char tempfile[FILENAME];
  70.     static int didpipe;
  71.  
  72.     initial_pos = NULL_POSITION;
  73.     if (filename == NULL || *filename == '\0')
  74.     {
  75.         if (curr_ac >= ac)
  76.         {
  77.             error("No current file");
  78.             return;
  79.         }
  80.         filename = av[curr_ac];
  81.     }
  82.     if (strcmp(filename, "#") == 0)
  83.     {
  84.         if (*previous_file == '\0')
  85.         {
  86.             error("no previous file");
  87.             return;
  88.         }
  89.         strtcpy(tempfile, previous_file, sizeof(tempfile));
  90.         filename = tempfile;
  91.         initial_pos = prev_pos;
  92.     }
  93.     if (strcmp(filename, "-") == 0)
  94.     {
  95.         /* 
  96.          * Use standard input.
  97.          */
  98.         if (didpipe)
  99.         {
  100.             error("Can view standard input only once");
  101.             return;
  102.         }
  103.         f = 0;
  104.     } else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
  105.     {
  106.         error(m);
  107.         return;
  108.     } else if ((f = open(filename, 0)) < 0)
  109.     {
  110.         error(errno_message(filename, message, sizeof(message)));
  111.         return;
  112.     }
  113.  
  114.     if (isatty(f))
  115.     {
  116.         /*
  117.          * Not really necessary to call this an error,
  118.          * but if the control terminal (for commands)
  119.          * and the input file (for data) are the same,
  120.          * we get weird results at best.
  121.          */
  122.         error("Can't take input from a terminal");
  123.         if (f > 0)
  124.             close(f);
  125.         return;
  126.     }
  127.  
  128. #if LOGFILE
  129.     /*
  130.      * If he asked for a log file and we have opened standard input,
  131.      * create the log file.  
  132.      * We take care not to blindly overwrite an existing file.
  133.      */
  134.     end_logfile();
  135.     if (f == 0 && namelogfile != NULL && is_tty)
  136.     {
  137.         int exists;
  138.         int answer;
  139.  
  140.         /*
  141.          * {{ We could use access() here. }}
  142.          */
  143.         exists = open(namelogfile, 0);
  144.         close(exists);
  145.         exists = (exists >= 0);
  146.  
  147.         if (exists && !force_logfile)
  148.         {
  149.             static char w[] = "WARNING: log file exists: ";
  150.             strcpy(message, w);
  151.             strtcpy(message+sizeof(w)-1, namelogfile,
  152.                 sizeof(message)-sizeof(w));
  153.             error(message);
  154.             answer = 'X';    /* Ask the user what to do */
  155.         } else
  156.             answer = 'O';    /* Create the log file */
  157.  
  158.     loop:
  159.         switch (answer)
  160.         {
  161.         case 'O': case 'o':
  162.             logfile = creat(namelogfile, 0644);
  163.             break;
  164.         case 'A': case 'a':
  165.             logfile = open(namelogfile, 1);
  166.             if (lseek(logfile, (offset_t)0, 2) < 0)
  167.             {
  168.                 close(logfile);
  169.                 logfile = -1;
  170.             }
  171.             break;
  172.         case 'D': case 'd':
  173.             answer = 0;    /* Don't print an error message */
  174.             break;
  175.         case 'q':
  176.             quit();
  177.         default:
  178.             putstr("\n  Overwrite, Append, or Don't log? ");
  179.             answer = getchr();
  180.             putstr("\n");
  181.             flush();
  182.             goto loop;
  183.         }
  184.  
  185.         if (logfile < 0 && answer != 0)
  186.         {
  187.             sprintf(message, "Cannot write to \"%s\"", 
  188.                 namelogfile);
  189.             error(message);
  190.         }
  191.     }
  192. #endif
  193.  
  194.     /*
  195.      * We are now committed to using the new file.
  196.      * Close the current input file and set up to use the new one.
  197.      */
  198.     if (file > 0)
  199.         close(file);
  200.     new_file = 1;
  201.     strtcpy(previous_file, current_file, sizeof(previous_file));
  202.     strtcpy(current_file, filename, sizeof(current_file));
  203.     prev_pos = position(TOP);
  204. #ifdef AMIGA
  205.     ispipe = ((f == 0) && !called_from_WB);
  206. #else
  207.     ispipe = (f == 0);
  208. #endif
  209.     if (ispipe)
  210.         didpipe = 1;
  211.     file = f;
  212.     ch_init( (ispipe) ? p_nbufs : f_nbufs );
  213.     init_mark();
  214.  
  215.     if (every_first_cmd != NULL)
  216.         first_cmd = every_first_cmd;
  217.  
  218.     if (is_tty)
  219.     {
  220.         int no_display = !any_display;
  221.         any_display = 1;
  222.         if (no_display && errmsgs > 0)
  223.         {
  224.             /*
  225.              * We displayed some messages on error output
  226.              * (file descriptor 2; see error() function).
  227.              * Before erasing the screen contents,
  228.              * display the file name and wait for a keystroke.
  229.              */
  230.             error(filename);
  231.         }
  232.         /*
  233.          * Indicate there is nothing displayed yet.
  234.          */
  235.         pos_clear();
  236.         if (initial_pos != NULL_POSITION)
  237.             jump_loc(initial_pos);
  238.     }
  239. }
  240.  
  241. /*
  242.  * Edit the next file in the command line list.
  243.  */
  244.     public void
  245. next_file(n)
  246.     int n;
  247. {
  248.     if (curr_ac + n >= ac)
  249.     {
  250.         if (quit_at_eof)
  251.             quit();
  252.         error("No (N-th) next file");
  253.     } else
  254.         edit(av[curr_ac += n]);
  255. }
  256.  
  257. /*
  258.  * Edit the previous file in the command line list.
  259.  */
  260.     public void
  261. prev_file(n)
  262.     int n;
  263. {
  264.     if (curr_ac - n < 0)
  265.         error("No (N-th) previous file");
  266.     else
  267.         edit(av[curr_ac -= n]);
  268. }
  269.  
  270. /*
  271.  * Copy a file directly to standard output.
  272.  * Used if standard output is not a tty.
  273.  */
  274.     static void
  275. cat_file()
  276. {
  277.     register int c;
  278.  
  279.     while ((c = ch_forw_get()) != EOF)
  280.         putchr(c);
  281.     flush();
  282. }
  283. #ifdef AMIGA
  284. /**************** amiga *****************************/
  285. /* Bob Leivian  4/28/87 fudge up things so it will work
  286.    when called from Work Bench */
  287.  
  288. char argvbuf[80];
  289. long old_dir;
  290. long current_dir;
  291.  
  292. #include "workbench/startup.h"
  293.  
  294. /* ignore AZTECs wb stuff */
  295. _wb_parse(ignore, ignore2)
  296. char *ignore;
  297. char *ignore2;
  298. {
  299.     return;
  300. #endif
  301.  
  302.  
  303. #ifdef NO_GETENV
  304. /* this requires the workbench disk --
  305.   ignore all environment variables for now */
  306. char * getenv(ignore)
  307. {
  308.     return NULL;
  309. }
  310. #endif
  311.  
  312. /*
  313.  * Entry point.
  314.  */
  315. main(argc, argv)
  316.     int argc;
  317.     char *argv[];
  318. {
  319.     char *getenv();
  320.     int i,j;
  321.     
  322. #ifdef AMIGA
  323. /***************** amiga ********************/
  324.     /* if we were called from the workbench we will have no args
  325.        but a pointer to WBstruct, get the filename from this structure */
  326.     if(argc == 0) {
  327.         struct WBStartup *WBmsg;
  328.         struct WBArg *p;
  329.  
  330.         /* the argv is really the work bench structure */
  331.         WBmsg = (struct WBStartup *) argv;
  332.         p = WBmsg->sm_ArgList;
  333.  
  334.         /* fake up the args now */
  335.         /* argv[0] = p->wa_Name; */
  336.         argv[0] = "less";
  337.         p++;  /* ignore first parm (name) */
  338.         strcpy(argvbuf, p->wa_Name);
  339.         argc = 2;
  340.         argv[1] = argvbuf;
  341.         argv[2] = NULL;
  342.  
  343.         /* we have to setup this icons current dir (& release it later) */
  344.         called_from_WB++;
  345.         current_dir = p->wa_Lock;
  346.         old_dir = CurrentDir(current_dir);
  347.     }
  348.  
  349.     /* save my name, in case someone renamed less to something else */
  350.     strcpy(prog_name, argv[0]);
  351.  
  352.     /* are we called to do a print function */
  353.     if (argc > 1 && 0 == strcmp(argv[1], "-p")) {
  354.  
  355.         extern int Enable_Abort;
  356.         long atol(), Output();
  357.         long his_lock, DupLock();
  358.  
  359.         /* this was a print only request */
  360.         argc--;
  361.         argv++;
  362.         Enable_Abort = 1;
  363.  
  364. #ifdef NO
  365.         /* if called from a workbench, he also passed the lock */
  366.         if (isdigit(*argv[1])) {
  367.  
  368.             called_from_WB++;
  369.             his_lock = atol(argv[1]);
  370.             argc--;
  371.             argv++;
  372.  
  373.             current_dir = DupLock(his_lock);
  374.             old_dir = CurrentDir(current_dir);
  375.         }
  376. #endif
  377.         start_print(argc, argv);
  378.  
  379.         if (called_from_WB) {
  380.             CurrentDir(old_dir);
  381.  
  382. #ifdef NO
  383.             /* close the stdout that my father opened */
  384.             his_lock = Output();
  385.             Close(his_lock); 
  386. #endif
  387.         }
  388.         exit(0);
  389.     }
  390. #endif
  391.  
  392.     /*
  393.      * Process command line arguments and LESS environment arguments.
  394.      * Command line arguments override environment arguments.
  395.      */
  396.     init_option();
  397.     scan_option(getenv("LESS"));
  398.     argv++;
  399.     while ( (--argc > 0) && 
  400.         (argv[0][0] == '-' || argv[0][0] == '+') && 
  401.          argv[0][1] != '\0')
  402.         scan_option(*argv++);
  403.  
  404. #if EDITOR
  405.     editor = getenv("EDITOR");
  406.     if (editor == NULL || *editor == '\0')
  407.         editor = "ed";
  408. #endif
  409.  
  410.     /*
  411.      * Set up list of files to be examined.
  412.      */
  413.     ac = argc;
  414.     av = argv;
  415.     
  416. #ifdef AMIGA
  417.     /* CLI doesn't expand templates link U*ix so we do it 'by hand' */
  418.  
  419.     for (i=0, j=0; i<ac; i++) {
  420.        int temp = 0;
  421.        char *p;
  422.        char *scdir();
  423.  
  424.         if(index(av[i], '*') || index(av[i], '?')) {
  425.  
  426.             /* this is a template it needs to be expanded */
  427.             while( (p = scdir(av[i])) && (j < MAXTEMPLATES)) {
  428.                  strcpy(&local_buffer[temp], p);
  429.                  local_av[j++] = &local_buffer[temp];
  430.                  temp += (strlen(&local_buffer[temp]) +1);
  431.                  if (temp > MAXARGVCHARS) break;
  432.             }
  433.          } else
  434.              local_av[j++] = av[i];
  435.     }
  436.     av = local_av;
  437.     local_av[j] = NULL;
  438.     ac = j;
  439. #endif
  440.  
  441.     curr_ac = 0;
  442.  
  443.     /*
  444.      * Set up terminal, etc.
  445.      */
  446. #ifdef AMIGA
  447.     is_tty = 1;
  448.     ttopen();
  449. #else
  450.     is_tty = isatty(1);
  451.     if (!is_tty)
  452.     {
  453.         /*
  454.          * Output is not a tty.
  455.          * Just copy the input file(s) to output.
  456.          */
  457.         if (ac < 1)
  458.         {
  459.             edit("-");
  460.             cat_file();
  461.         } else
  462.         {
  463.             do
  464.             {
  465.                 edit((char *)NULL);
  466.                 if (file >= 0)
  467.                     cat_file();
  468.             } while (++curr_ac < ac);
  469.         }
  470.         exit(0);
  471.     }
  472. #endif
  473.  
  474.     raw_mode(1);
  475.     get_term();
  476.     open_getchr();
  477.     init();
  478.  
  479.     if (setjmp(main_loop))
  480.         quit();
  481.     init_signals();
  482.  
  483.     /*
  484.      * Select the first file to examine.
  485.      */
  486.     if (ac < 1)
  487.         edit("-");    /* Standard input */
  488.     else 
  489.     {
  490.         /*
  491.          * Try all the files named as command arguments.
  492.          * We are simply looking for one which can be
  493.          * opened without error.
  494.          */
  495.         do
  496.         {
  497.             edit((char *)NULL);
  498.         } while (file < 0 && ++curr_ac < ac);
  499.     }
  500.  
  501.     if (file >= 0)
  502.         commands();
  503.     quit();
  504.     /*NOTREACHED*/
  505. }
  506.  
  507. /*
  508.  * Copy a string, truncating to the specified length if necessary.
  509.  * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
  510.  */
  511. strtcpy(to, from, len)
  512.     char *to;
  513.     char *from;
  514.     int len;
  515. {
  516.     strncpy(to, from, len);
  517.     to[len-1] = '\0';
  518. }
  519.  
  520. /*
  521.  * Exit the program.
  522.  */
  523.     public void
  524. quit()
  525. {
  526.     /*
  527.      * Put cursor at bottom left corner, clear the line,
  528.      * reset the terminal modes, and exit.
  529.      */
  530. #if LOGFILE
  531.     end_logfile();
  532. #endif
  533.     lower_left();
  534.     clear_eol();
  535.     deinit();
  536.  
  537.     flush();
  538.     raw_mode(0);
  539.     
  540. #ifdef AMIGA
  541.     ttclose();
  542.  
  543.     if(called_from_WB)
  544.         CurrentDir(old_dir);
  545. #endif
  546.  
  547.     exit(0);
  548. }
  549.